// 保存当前需要收集的响应式函数
let activeReactiveFn = null   

//Depend优化：
// 1.depend方法
//2.使用Set来保存依赖函数，而不是数组
class Depend{
    constructor(){
        this.reactiveFns = new Set()
    }
    addDepend(reactiveFn){
        this.reactiveFns.add(reactiveFn)
    }

    depend(){
        if(activeReactiveFn){
            this.reactiveFns.add(activeReactiveFn)
        }
    }

    notify(){
        this.reactiveFns.forEach(fn=>{
            fn()
        })
    }
}


//封装一个响应式的函数

function watchFn(fn){
    activeReactiveFn = fn
    fn()
    activeReactiveFn = null
}

// 封装一个获取depend函数
const targetMap = new WeakMap()
function getDepend(target,key) {
    //根据target对象获取map的过程
    let map = targetMap.get(target)
    if(!map){
        map = new Map()
        targetMap.set(target,map)
    }

    //根据key获取depend对象
    let depend = map.get(key)
    if(!depend){
        depend =  new Depend()
        map.set(key,depend)
    }
    return depend
}

function reactive(obj) {
    return new Proxy(obj,{
        get:function (target,key,receiver) {
            // 根据target，key获取对应的depend
            const depend = getDepend(target,key)
            // depend.addDepend(activeReactiveFn)
            depend.depend()
            return Reflect.get(target,key,receiver)
        },
        set:function (target,key,newValue,receiver) {
            Reflect.set(target,key,newValue,receiver)
            // depend.notify()
            const depend = getDepend(target,key)
            depend.notify()
        }
    }
    )   
}

//对象的响应式
const obj ={
    name:"why",
    age:18
}

//监听对象的属性变量：Proxy(vue3)/Object.defineProperty(vue2)
const objProxy = new Proxy(obj,{
    get:function (target,key,receiver) {
        // 根据target，key获取对应的depend
        const depend = getDepend(target,key)
        // depend.addDepend(activeReactiveFn)
        depend.depend()
        return Reflect.get(target,key,receiver)
    },
    set:function (target,key,newValue,receiver) {
        Reflect.set(target,key,newValue,receiver)
        // depend.notify()
        const depend = getDepend(target,key)
        depend.notify()
    }
}
)

// const info={
//     address:"广州市",
//     height:1.88
// }

// const infoProxy = reactive(info)


// watchFn(()=>{
//     console.log(infoProxy.address)
// })

// infoProxy.address = "北京市"

const foo = reactive({
    name:"foo"
})

watchFn(()=>{
    console.log(foo.name)
})

foo.name = "bar"